]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Add demands attention support to the messagetray
authorAdel Gadllah <adel.gadllah@gmail.com>
Mon, 22 Feb 2010 18:53:41 +0000 (19:53 +0100)
committerAdel Gadllah <adel.gadllah@gmail.com>
Mon, 22 Feb 2010 19:09:43 +0000 (20:09 +0100)
Inform the user about demands attention events using the messagetray.

Clicking on the notification icon moves the user to the window.

It differentiates between newly started apps and windows of already running apps, by showing different banners for this cases.

It is based on Jon Nettleton's "window attention" extension.

https://bugzilla.gnome.org/show_bug.cgi?id=610594

js/ui/Makefile.am
js/ui/main.js
js/ui/windowAttentionHandler.js [new file with mode: 0644]

index 22f027efc811cbc533b430cc493f85b9ad3d8448..974cc6043625a97b9a3c6a3072208495b5d8ca57 100644 (file)
@@ -29,6 +29,7 @@ dist_jsui_DATA =              \
        tweener.js              \
        widget.js               \
        widgetBox.js            \
+       windowAttentionHandler.js      \
        windowManager.js        \
        workspacesView.js       \
        workspaceSwitcherPopup.js       \
index 902ee5b02897b35986c8b1f0f159f5c971bec683..f1eb302b568a866b360292ab18832f8ed1464eb6 100644 (file)
@@ -22,6 +22,7 @@ const PlaceDisplay = imports.ui.placeDisplay;
 const RunDialog = imports.ui.runDialog;
 const LookingGlass = imports.ui.lookingGlass;
 const NotificationDaemon = imports.ui.notificationDaemon;
+const WindowAttentionHandler = imports.ui.windowAttentionHandler;
 const ShellDBus = imports.ui.shellDBus;
 const Sidebar = imports.ui.sidebar;
 const WindowManager = imports.ui.windowManager;
@@ -39,6 +40,7 @@ let lookingGlass = null;
 let wm = null;
 let notificationDaemon = null;
 let messageTray = null;
+let windowAttentionHandler = null;
 let recorder = null;
 let shellDBusService = null;
 let modalCount = 0;
@@ -116,6 +118,7 @@ function start() {
     sidebar = new Sidebar.Sidebar();
     wm = new WindowManager.WindowManager();
     notificationDaemon = new NotificationDaemon.NotificationDaemon();
+    windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler();
     messageTray = new MessageTray.MessageTray();
 
     _startDate = new Date();
diff --git a/js/ui/windowAttentionHandler.js b/js/ui/windowAttentionHandler.js
new file mode 100644 (file)
index 0000000..58a2c08
--- /dev/null
@@ -0,0 +1,109 @@
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const Clutter = imports.gi.Clutter;
+const Lang = imports.lang;
+const Shell = imports.gi.Shell;
+const Meta = imports.gi.Meta;
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
+
+const Main = imports.ui.main;
+const MessageTray = imports.ui.messageTray;
+
+function WindowAttentionHandler() {
+    this._init();
+}
+
+WindowAttentionHandler.prototype = {
+    _init : function() {
+        let display = global.screen.get_display();
+        display.connect('window-demands-attention', Lang.bind(this, this._onWindowDemandsAttention));
+        let tracker = Shell.WindowTracker.get_default();
+        this._startupIds = {};
+        tracker.connect('startup-sequence-changed', Lang.bind(this, this._onStartupSequenceChanged));
+    },
+
+    _onStartupSequenceChanged : function(tracker) {
+        let sequences = tracker.get_startup_sequences();
+        this._startupIds = {};
+        for(let i = 0; i < sequences.length; i++) {
+            this._startupIds[sequences[i].get_id()] = true;
+        }
+    },
+
+    _sourceId : function(appId) {
+        return 'attention-' + appId;
+    },
+
+    _getTitle : function(app, window) {
+        if (this._startupIds[window.get_startup_id()])
+            return app.get_name();
+        else
+            return window.title;
+    },
+
+    _getBanner : function(app, window) {
+        if (this._startupIds[window.get_startup_id()])
+            return _("%s has finished starting").format(app.get_name());
+        else
+            return _("'%s' is ready").format(window.title);
+    },
+
+    _onWindowDemandsAttention : function(display, window) {
+        // We don't want to show the notification when the window is already focused,
+        // because this is rather pointless.
+        // Some apps (like GIMP) do things like setting the urgency hint on the
+        // toolbar windows which would result into a notification even though GIMP itself is
+        // focused.
+        // We are just ignoring the hint on skip_taskbar windows for now.
+        // (Which is the same behaviour as with metacity + panel)
+
+        if (!window || window.has_focus() || window.is_skip_taskbar())
+            return;
+
+        let tracker = Shell.WindowTracker.get_default();
+        let app = tracker.get_window_app(window);
+
+        let source = Main.messageTray.getSource(this._sourceId(app.get_id()));
+        if (source == null) {
+            source = new Source(this._sourceId(app.get_id()), app, window);
+            Main.messageTray.add(source);
+            source.connect('clicked', Lang.bind(this, function() { source.destroy(); }));
+        }
+
+        let notification = new MessageTray.Notification(source, this._getTitle(app, window), this._getBanner(app, window), true);
+        source.notify(notification);
+
+        window.connect('notify::title', Lang.bind(this, function(win) {
+                                                            notification.update(this._getTitle(app, win), this._getBanner(app, win), false);
+                                                        }));
+        window.connect('notify::demands-attention', Lang.bind(this, function() { source.destroy() }));
+        window.connect('focus', Lang.bind(this, function() { source.destroy() }));
+        window.connect('unmanaged', Lang.bind(this, function() { source.destroy() }));
+
+    }
+}
+
+function Source(sourceId, app, window) {
+    this._init(sourceId, app, window);
+}
+
+Source.prototype = {
+    __proto__ : MessageTray.Source.prototype,
+
+    _init: function(sourceId, app, window) {
+        MessageTray.Source.prototype._init.call(this, sourceId);
+        this._window = window;
+        this._app = app;
+    },
+
+    createIcon : function(size) {
+        return this._app.create_icon_texture(size);
+    },
+
+    clicked : function() {
+        Main.activateWindow(this._window);
+        MessageTray.Source.prototype.clicked.call(this);
+    }
+
+}